package com.woniu108.order.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.db.sql.Order;
import cn.hutool.json.JSONUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu108.carService.commos.exception.orderProduct.OrderProductException;
import com.woniu108.carService.commos.exception.orderProduct.OrderProductExceptionCode;
import com.woniu108.carService.commos.util.RedisKey;
import com.woniu108.carService.commos.util.RedisUtil;
import com.woniu108.carService.commos.util.StaticData;
import com.woniu108.order.client.PersonClient;
import com.woniu108.order.client.ProductClient;
import com.woniu108.order.mapper.OrderProductMapper;
import com.woniu108.order.mapper.OrderRefundMapper;
import com.woniu108.order.model.dto.OrderProductDto;
import com.woniu108.order.model.dto.OrderRefundDto;
import com.woniu108.order.model.form.OrderRefundAgreeRefundForm;
import com.woniu108.order.model.form.OrderRefundAgreeRefundParam;
import com.woniu108.order.model.model.OrderProduct;
import com.woniu108.order.model.model.OrderRefund;
import com.woniu108.order.model.param.OrderProductRefundApplyParam;
import com.woniu108.order.model.param.OrderRefundDisagreeParam;
import com.woniu108.order.service.OrderProductService;
import com.woniu108.order.service.OrderRefundService;
import com.woniu108.product.form.FailedSaleForm;
import org.aspectj.weaver.ast.Or;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 订单退款申请表 服务实现类
 * </p>
 *
 * @author yanxi
 * @since 2024-05-23
 */
@Service
public class OrderRefundServiceImpl extends ServiceImpl<OrderRefundMapper, OrderRefund> implements OrderRefundService {
    @Resource
    OrderRefundMapper orderRefundMapper;
    @Resource
    OrderProductService orderProductService;
    @Resource
    OrderProductMapper orderProductMapper;
    @Resource
    PersonClient personClient;
    @Resource
    private AlipayClient alipayClient;
    @Resource
    private ProductClient productClient;
    @Resource
    private RedisUtil redisUtil;
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean insertOrderRefund(OrderProductRefundApplyParam param) {
        OrderProductDto orderProductDto = orderProductService.selectOneOrderByOrderNum(param.getOrderProductNum());
        //判断订单存在
        if(orderProductDto==null){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_NULL);
        }
        //判断用户有权
        if(!orderProductDto.getUserId().equals(param.getUserId())){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_USER_NOT_POWER);
        }
        //判断申请存在并且正在受理
        OrderRefund refund = orderRefundMapper.selectOne(new QueryWrapper<OrderRefund>().eq("order_product_num",orderProductDto.getOrderProductNum()));
        if(refund!=null){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_REFUND_HAVE_APPLY);
        }
        OrderRefund orderRefund = BeanUtil.toBean(param, OrderRefund.class);
        orderRefund.setRefundTime(LocalDateTimeUtil.parse(param.getRefundTime(), "yyyy-MM-dd HH:mm:ss"));
        orderRefund.setOrderPrice(orderProductDto.getOrderPrice());
        orderRefund.setRefundState(StaticData.ORDER_REFUND_WAIT);
        orderRefundMapper.insert(orderRefund);

        OrderProduct orderProduct = orderProductMapper.selectById(orderProductDto.getOrderProductNum());
        //redis保存退款前订单状态
        redisUtil.setString(RedisKey.orderProductPreState(orderProduct.getOrderProductNum()),orderProduct.getOrderProductState()+"");

        orderProduct.setOrderProductState(StaticData.ORDER_PRODUCT_STATE_REFUND_WAIT);
        orderProductMapper.updateById(orderProduct);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean agree(OrderRefundAgreeRefundParam param) throws AlipayApiException {
        OrderProductDto orderProductDto = orderProductService.selectOneOrderByOrderNum(param.getOrderProductNum());
        if(orderProductDto==null){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_NULL);
        }
        OrderRefund refund = orderRefundMapper.selectOne(new QueryWrapper<OrderRefund>().eq("order_product_num",orderProductDto.getOrderProductNum()));
        if(refund==null){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_REFUND_NO_EXISTED);
        }
        if(!orderProductDto.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_REFUND_WAIT)){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_NO_APPLY);
        }
        if(!refund.getRefundState().equals(StaticData.ORDER_REFUND_WAIT)){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_REFUND_NO_WAIT);
        }
//        //退款金额是否大于订单金额
//        if(param.getOrderPrice()>(Double.parseDouble(orderProductDto.getOrderPrice().toString()))){
//            throw new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_REFUND_PRICE_SUPER);
//        }

        refund.setRefundState(StaticData.ORDER_REFUND_AGREE);
        refund.setDealTime(LocalDateTime.now());
        orderRefundMapper.updateById(refund);

        AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
        String out_trade_no=param.getOrderProductNum();
        String refund_reason="退货退款";
        //标识一次退款请求，同一笔交易分多次退款的话，out_request_no每次传值都不能重复，必须保证唯一性

        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"refund_amount\":\""+ orderProductDto.getOrderPrice() +"\","
                + "\"refund_reason\":\""+ refund_reason +"\","
                + "\"out_request_no\":\""+ UUID.randomUUID() +"\"}");
        String result=alipayClient.execute(alipayRequest).getBody();
//        String code = JSONUtil.parseObj(JSONUtil.parseObj(result).get("alipay_trade_refund_response").toString()).get("code").toString();
//        String fundChange = JSONUtil.parseObj(JSONUtil.parseObj(result).get("alipay_trade_refund_response").toString()).get("fund_change").toString();

        try {
            AlipayTradeRefundResponse response = alipayClient.execute(alipayRequest);
            if(response.isSuccess()){
                //退款操作
                //扣除积分
                personClient.reduceUserScore(orderProductDto.getUserId(),orderProductDto.getOrderPrice().intValue(),StaticData.SCORE_SHOPPING);
                //还商品余量
                ArrayList<Map<Object, Object>> maps =orderProductDto.getProductInfos();
                for (Map<Object,Object> map:maps){
                    String pInfoId = map.get("pInfoId").toString();
                    String productNum = map.get("number").toString();
                    FailedSaleForm form = new FailedSaleForm();
                    form.setNum(Integer.valueOf(productNum));
                    form.setPInfoId(Integer.valueOf(pInfoId));
                    productClient.failedSale(form);
                }
                //修改订单退款状态
                OrderProduct orderProduct = new OrderProduct();
                orderProduct.setOrderProductState(StaticData.ORDER_PRODUCT_STATE_REFUND_FINISHED);
                orderProductMapper.updateById(orderProduct);

                //删除redis的退款前原状态
                redisUtil.delete(RedisKey.orderProductPreState(orderProduct.getOrderProductNum()));
                return true;
            }else {
                return false;
            }
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Boolean cancel(String orderProductNum,String userId) {
        OrderRefund refund = orderRefundMapper.selectOne(new QueryWrapper<OrderRefund>().eq("order_product_num",orderProductNum));
        OrderProduct orderProduct = orderProductMapper.selectOne(new QueryWrapper<OrderProduct>().eq("order_product_num",orderProductNum));
        if(refund==null){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_REFUND_NO_EXISTED);
        }
        if(!refund.getRefundState().equals(StaticData.ORDER_REFUND_WAIT)){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_REFUND_NO_WAIT);
        }
        if(orderProduct==null){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_NULL);
        }
        if(!orderProduct.getUserId().equals(userId)){
            new OrderProductException(OrderProductExceptionCode.ORDER_PRODUCT_USER_NOT_POWER);
        }

        orderRefundMapper.delete(new QueryWrapper<OrderRefund>().eq("order_product_num",refund.getOrderProductNum()));

        //修改商品订单状态
        orderProduct.setOrderProductState(Integer.valueOf(redisUtil.getString(RedisKey.orderProductPreState(orderProductNum))));
        orderProductMapper.updateById(orderProduct);

        //删除redis的退款前原状态
        redisUtil.delete(RedisKey.orderProductPreState(orderProduct.getOrderProductNum()));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean disagree(OrderRefundDisagreeParam param) {
        OrderRefund refund = orderRefundMapper.selectById(param.getOrderProductNum());
        OrderProduct orderProduct = orderProductMapper.selectOne(new QueryWrapper<OrderProduct>().eq("order_product_num",param.getOrderProductNum()));

        if(refund==null){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_REFUND_NO_EXISTED);
        }
        if(orderProduct==null){
            throw new OrderProductException(OrderProductExceptionCode.ORDER_NULL);
        }
        if(orderProduct.getOrderProductState().equals(StaticData.ORDER_PRODUCT_STATE_REFUND_FINISHED)){
            throw new OrderProductException(OrderProductExceptionCode.REFUND_FINISHED);
        }
        //处理申请
        refund.setRefundState(StaticData.ORDER_REFUND_DISAGREE);
        LocalDateTime now = LocalDateTimeUtil.now();
        refund.setDealTime(now);
        refund.setReason(param.getReason());
        orderRefundMapper.delete(new QueryWrapper<OrderRefund>().eq("order_product_num",refund.getOrderProductNum()));
        //处理退款申请
        HashMap<String, Object> map = new HashMap<>();
        map.put("orderProductNum",refund.getOrderProductNum());
        map.put("refundTime",refund.getRefundTime().toString());
        map.put("refundReason",refund.getRefundReason());
        map.put("refundState",refund.getRefundState()+"");
        map.put("dealTime",refund.getDealTime().toString());
        map.put("dealReason",refund.getReason());
        redisUtil.hmset(RedisKey.orderProductRefund(refund.getOrderProductNum()),map);

        //修改商品订单状态
        orderProduct.setOrderProductState(Integer.valueOf(redisUtil.getString(RedisKey.orderProductPreState(orderProduct.getOrderProductNum()))));
        orderProductMapper.updateById(orderProduct);

        //删除redis的退款前原状态
        redisUtil.delete(RedisKey.orderProductPreState(orderProduct.getOrderProductNum()));
        return true;
    }

    @Override
    public List<OrderRefundDto> queryAllRefund() {
        List<OrderRefund> orderRefunds = orderRefundMapper.selectList(new QueryWrapper<OrderRefund>());
        ArrayList<OrderRefundDto> orderRefundDtos = new ArrayList<>();
        for (OrderRefund orderRefund:orderRefunds){
            if(orderRefund.getRefundState().equals(StaticData.ORDER_REFUND_WAIT)){
                OrderRefundDto orderRefundDto = BeanUtil.toBean(orderRefund, OrderRefundDto.class);
                orderRefundDtos.add(orderRefundDto);
            }
        }
        return orderRefundDtos;
    }

    @Override
    public Map<Object, Object> selectRefundByOrderProductNum(String orderProductNum) {
        if(redisUtil.exist(RedisKey.orderProductRefund(orderProductNum))){
            Map<Object, Object> map = redisUtil.hgetall(RedisKey.orderProductRefund(orderProductNum));
            return map;
        }else {
            return null;
        }
    }


}
